package com.xcity.game.proxy.utils;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import com.xcity.game.proxy.DynamicProxyInfo;
import com.xcity.game.proxy.utils.DynamicProxyUtils.ProxyClass;

import javassist.CtClass;
import javassist.CtField;

public class MethodInfo {

	public Method method;
	public DynamicProxyInfo annotation;
	
	public CtField cfield; // 对应代理类中的字段（只有getter方法才有可能有）
	private static int fieldCounter;
	
	public MethodInfo(Method method) {
		this.method = method;
	}
	
	/*package*/ void init(CtClass declaring) {
		DynamicProxyInfo anno = this.annotation = method.getAnnotation(DynamicProxyInfo.class);
		Method method = this.method;
		if (anno != null && anno.proxy()
				&& isGetter(method)
				&& !method.getReturnType().isPrimitive()) { // 代理该getter方法的返回值类型对应的类
			try {
				ProxyClass pc = DynamicProxyUtils.getProxyClass(method.getReturnType());
				CtClass cclass = pc.cclass;
				this.cfield = DynamicProxyUtils.makeField(declaring, cclass, "proxy_field" + ++fieldCounter);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	@Override
	public int hashCode() {
		return 31 * method.getModifiers() + 31 * method.getName().hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof MethodInfo)) {
			return false;
		}
		MethodInfo other = (MethodInfo) obj;
		if (!method.getName().equals(other.method.getName())) {
			return false;
		}
		Class<?>[] params1 = method.getParameterTypes();
		Class<?>[] params2 = other.method.getParameterTypes();
		if (params1.length != params2.length) {
			return false;
		}
		for (int i = 0, len = params1.length; i < len; i++) {
			Class<?> p1 = params1[i];
			Class<?> p2 = params2[i];
			if (p1 != p2) {
				return false;
			}
		}
		return true;
	}
	
	/*package*/ static boolean isGetter(Method method) {
		if (!Modifier.isPublic(method.getModifiers())) {
			return false;
		}
		if (method.getReturnType() == void.class) {
			return false;
		}
		if (method.getParameterCount() != 0) {
			return false;
		}
		String name = method.getName();
		if (name.startsWith("get")) {
			if (method.getReturnType() == boolean.class) {
				return false;
			}
			if (!Character.isUpperCase(name.charAt(3))) {
				return false;
			}
			return true;
		}
		if (name.startsWith("is")) {
			if (method.getReturnType() != boolean.class) {
				return false;
			}
			if (!Character.isUpperCase(name.charAt(2))) {
				return false;
			}
			return true;
		}
		return false;
	}
	
}
